﻿using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.SessionState;
using System.Text.RegularExpressions;

namespace OF.Controls
{
    /// <summary>
    /// 文件名称：分页控件
    /// </summary>
    [DefaultProperty("CurrentPageIndex"), DefaultEvent("PageChanged"), ToolboxData("<{0}:OFPager runat=server/>")]
    public class OFPager : System.Web.UI.WebControls.WebControl, IRequiresSessionState
    {
        public event EventHandler PageChanged;

        #region 私有字段

        //数据
        private int currentPageIndex = 1;
        private int pageSize = 10;
        private int recordCount = 1;
        private int pageCount = 1;
        //行为
        private bool alwaysShow;
        private bool alwaysShowFirstLastPageNumber = true;
        private bool showSelect;
        private bool showFirstLast = true;
        private bool showPrevNext = true;
        private bool showTotalPageText;
        private bool showSizeSelect;
        private int sidePageCount = 1;
        private bool rememberPage = false;
        //导航
        private string firstPageText = "首页";//first
        private string prevPageText = "上一页";//next
        private string nextPageText = "下一页";//prev
        private string lastPageText = "尾页";//last
        private string totalPageText = "(当前 c/t 页 每页 i/s 条)";
        //外观
        private string currentPageButtonClass = "page-cur";
        private string firstButtonsClass = "page-start";
        private string lastButtonsClass = "page-end";
        private string nextButtonsClass = "page-next";
        private string prevButtonsClass = "page-prev";
        private string totalPageTextClass = "page-skip";
        //其他
        private const string KEY_URL = "Pager_keyUrl";
        private const string KEY_SEARCHER = "Pager_keySearcher";
        private const string KEY_ORDER = "Pager_keyOrder";
        private const string KEY_INDEX = "Pager_keyIndex";

        #endregion

        #region 属性

        #region 数据属性

        /// <summary>
        /// 当前页的页码值
        /// </summary>
        [Browsable(true), Themeable(true), Category("Data"), DefaultValue(1), Description("当前页的页码值")]
        public int CurrentPageIndex
        {
            get
            {
                if (rememberPage)
                {
                    if (Page.Session[KEY_URL] != null
                        && Page.Session[KEY_URL].ToString() == Page.Request.Url.AbsoluteUri
                        && Page.Session[KEY_INDEX] != null)
                    {
                        currentPageIndex = Convert.ToInt32(Page.Session[KEY_INDEX]);
                    }
                }
                else if (ViewState["currentPageIndex"] != null)
                {
                    currentPageIndex = Convert.ToInt32(ViewState["currentPageIndex"]);
                }
                return currentPageIndex;
            }
            set
            {
                currentPageIndex = value;
                if (rememberPage)
                {
                    Page.Session[KEY_INDEX] = currentPageIndex;
                }
                else
                {
                    ViewState["currentPageIndex"] = currentPageIndex;
                }
            }
        }
        /// <summary>
        /// 每页显示的记录数
        /// </summary>
        [Browsable(true), Themeable(true), Category("Data"), DefaultValue(10), Description("每页显示的记录数")]
        public int PageSize
        {
            get
            {
                if (ViewState["pageSize"] != null)
                {
                    pageSize = Convert.ToInt32(ViewState["pageSize"]);
                }
                return pageSize;
            }
            set
            {
                if (value > 0)
                {
                    ViewState["pageSize"] = pageSize = value;
                }
                CountPage();
            }
        }
        /// <summary>
        /// 总记录数
        /// </summary>
        [Browsable(true), Themeable(true), Category("Data"), DefaultValue(1), Description("总记录数")]
        public int RecordCount
        {
            get
            {
                if (ViewState["recordCount"] != null)
                {
                    recordCount = Convert.ToInt32(ViewState["recordCount"]);
                }
                return recordCount;
            }
            set
            {
                if (value >= 0)
                {
                    ViewState["recordCount"] = value;
                }
                CountPage();
            }
        }
        /// <summary>
        /// 所有记录的页数
        /// </summary>
        [Browsable(true), Themeable(true), Category("Data"), DefaultValue(1), Description("所有记录的页数"), ReadOnly(true)]
        public int PageCount
        {
            get { return pageCount; }
        }
        /// <summary>
        /// 页面数据的搜索条件
        /// </summary>
        [Browsable(false), Category("Data"), Description("页面数据的搜索条件")]
        public string SearchCriteria
        {
            get
            {
                if (rememberPage)
                {
                    if (Page.Session[KEY_URL] != null
                        && Page.Session[KEY_URL].ToString() == Page.Request.Url.AbsoluteUri
                        && Page.Session[KEY_SEARCHER] != null)
                    {
                        return Page.Session[KEY_SEARCHER].ToString();
                    }
                }
                else if (ViewState[KEY_SEARCHER] != null)
                {
                    return ViewState[KEY_SEARCHER].ToString();
                }
                return string.Empty;
            }
            set
            {
                if (rememberPage)
                {
                    Page.Session[KEY_SEARCHER] = value;
                }
                else
                {
                    ViewState[KEY_SEARCHER] = value;
                }
            }
        }
        /// <summary>
        /// 页面数据的搜索条件
        /// </summary>
        [Browsable(false), Category("Data"), Description("页面数据的排序条件")]
        public string OrderCriteria
        {
            get
            {
                if (rememberPage)
                {
                    if (Page.Session[KEY_URL] != null
                        && Page.Session[KEY_URL].ToString() == Page.Request.Url.AbsoluteUri
                        && Page.Session[KEY_ORDER] != null)
                    {
                        return Page.Session[KEY_ORDER].ToString();
                    }
                }
                else if (ViewState[KEY_ORDER] != null)
                {
                    return ViewState[KEY_ORDER].ToString();
                }
                return null;
            }
            set
            {
                if (rememberPage)
                {
                    Page.Session[KEY_ORDER] = value;
                }
                else
                {
                    ViewState[KEY_ORDER] = value;
                }
            }
        }

        #endregion

        #region 行为属性
        /// <summary>
        /// 是否总是显示分页控件
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(false), Description("是否总是显示分页控件")]
        public bool AlwaysShow
        {
            get { return alwaysShow; }
            set { alwaysShow = value; }
        }
        /// <summary>
        /// 是否总是显示首页和尾页的页码链接
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(true), Description("是否总是显示首页和尾页的页码链接")]
        public bool AlwaysShowFirstLastPageNumber
        {
            get { return alwaysShowFirstLastPageNumber; }
            set { alwaysShowFirstLastPageNumber = value; }
        }
        /// <summary>
        /// 是否显示下拉框
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(false), Description("是否显示下拉框")]
        public bool ShowSelect
        {
            get { return showSelect; }
            set { showSelect = value; }
        }
        /// <summary>
        /// 是否显示首页和尾页链接
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(true), Description("是否显示首页和尾页链接")]
        public bool ShowFirstLast
        {
            get { return showFirstLast; }
            set { showFirstLast = value; }
        }
        /// <summary>
        /// 是否显示上一页和下一页链接
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(true), Description("是否显示上一页和下一页链接")]
        public bool ShowPrevNext
        {
            get { return showPrevNext; }
            set { showPrevNext = value; }
        }
        /// <summary>
        /// 是否显示当前总页数，显示方式：((当前 1/3 页 每页 10/23 条))
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(false), Description("是否显示当前总页数")]
        public bool ShowTotalPageText
        {
            get { return showTotalPageText; }
            set { showTotalPageText = value; }
        }

        /// <summary>
        /// 是否显示页面大小选择下拉框
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(false), Description("是否显示页面大小选择下拉框")]
        public bool ShowSizeSelect
        {
            get { return showSizeSelect; }
            set { showSizeSelect = value; }
        }

        /// <summary>
        /// 当前页前后显示的页码数,范围0-4
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(1), Description("当前页前后显示的页码数,范围0-4")]
        public int SidePageCount
        {
            get { return sidePageCount; }
            set
            {
                if (value < 0)
                {
                    sidePageCount = 0;
                }
                else if (value > 5)
                {
                    sidePageCount = 4;
                }
                else
                {
                    sidePageCount = value;
                }
            }
        }

        /// <summary>
        /// 是否记住页码
        /// </summary>
        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(false), Description("是否记住页码")]
        public bool RememberPage
        {
            get { return rememberPage; }
            set { rememberPage = value; }
        }
        #endregion

        #region 导航属性
        /// <summary>
        /// 首页链接显示的文字
        /// </summary>
        [Browsable(true), Themeable(true), Category("Navigation"), DefaultValue("首页"), Description("首页链接显示的文字")]
        public string FirstPageText
        {
            get { return firstPageText; }
            set { firstPageText = value; }
        }
        /// <summary>
        /// 尾页链接显示的文字
        /// </summary>
        [Browsable(true), Themeable(true), Category("Navigation"), DefaultValue("尾页"), Description("尾页链接显示的文字")]
        public string LastPageText
        {
            get { return lastPageText; }
            set { lastPageText = value; }
        }
        /// <summary>
        /// 上一页链接显示的文字
        /// </summary>
        [Browsable(true), Themeable(true), Category("Navigation"), DefaultValue("上一页"), Description("上一页链接显示的文字")]
        public string PrevPageText
        {
            get { return prevPageText; }
            set { prevPageText = value; }
        }
        /// <summary>
        /// 下一页链接显示的文字
        /// </summary>
        [Browsable(true), Themeable(true), Category("Navigation"), DefaultValue("下一页"), Description("下一页链接显示的文字")]
        public string NextPageText
        {
            get { return nextPageText; }
            set { nextPageText = value; }
        }
        /// <summary>
        /// 总页码显示格式字符串,默认:(当前 c/t 页 每页 i/s 条)
        ///     当前页用 c 代替，总页码用 t 代替
        ///     每页显示数用 i 代替,总记录数用 s 代替，不区分大小写
        /// </summary>
        [Browsable(true), Themeable(true), Category("Navigation"), DefaultValue("(共 c/t 页)"), Description("总页码显示格式字符串")]
        public string TotalPageText
        {
            get { return totalPageText; }
            set { totalPageText = value; }
        }

        #endregion

        #region 外观属性
        /// <summary>
        /// 应用于首页链接的 CSS 类名
        /// </summary>
        [Browsable(true), Themeable(true), DefaultValue("first"), Category("Appearance"), Description("应用于首页链接的 CSS 类名")]
        public string FirstButtonsClass
        {
            get { return firstButtonsClass; }
            set { firstButtonsClass = value; }
        }
        /// <summary>
        /// 应用于当前页链接的 CSS 类名
        /// </summary>
        [Browsable(true), Themeable(true), DefaultValue("current"), Category("Appearance"), Description("应用于当前页链接的 CSS 类名")]
        public string CurrentPageButtonClass
        {
            get { return currentPageButtonClass; }
            set { currentPageButtonClass = value; }
        }
        /// <summary>
        /// 应用于总页码字符串的 CSS 类名
        /// </summary>
        [Browsable(true), Themeable(true), DefaultValue("total"), Category("Appearance"), Description("应用于总页码字符串的 CSS 类名")]
        public string TotalPageTextClass
        {
            get { return totalPageTextClass; }
            set { totalPageTextClass = value; }
        }

        /// <summary>
        /// 应用于尾页链接的 CSS 类名
        /// </summary>
        [Browsable(true), Themeable(true), DefaultValue("first"), Category("Appearance"), Description("应用于尾页链接的 CSS 类名")]
        public string LastButtonsClass
        {
            get { return lastButtonsClass; }
            set { lastButtonsClass = value; }
        }

        /// <summary>
        /// 应用于下一页链接的 CSS 类名
        /// </summary>
        [Browsable(true), Themeable(true), DefaultValue("first"), Category("Appearance"), Description("应用于下一页链接的 CSS 类名")]
        public string NextButtonsClass
        {
            get { return nextButtonsClass; }
            set { nextButtonsClass = value; }
        }

        /// <summary>
        /// 应用于上一页链接的 CSS 类名
        /// </summary>
        [Browsable(true), Themeable(true), DefaultValue("first"), Category("Appearance"), Description("应用于上一页链接的 CSS 类名")]
        public string PrevButtonsClass
        {
            get { return prevButtonsClass; }
            set { prevButtonsClass = value; }
        }

        #endregion

        #endregion

        public OFPager()
        {
            base.CssClass = "ofpage";
        }

        protected override void OnLoad(EventArgs e)
        {
            //base.OnLoad(e);

            //生成页面的__doPostBack脚本函数
            Page.ClientScript.GetPostBackEventReference(new PostBackOptions(this));
            //处理__doPostBack回传参数
            if (Page.IsPostBack)
            {
                if (Page.Request.Form["__EVENTTARGET"] != null)
                {
                    string target = Page.Request.Form["__EVENTTARGET"];
                    if (target == ID)
                    {
                        if (Page.Request.Form["__EVENTARGUMENT"] != null &&
                            !string.IsNullOrEmpty(Page.Request.Form["__EVENTARGUMENT"]))
                        {
                            CurrentPageIndex = Convert.ToInt32(Page.Request.Form["__EVENTARGUMENT"]);
                        }
                        else if (Page.Request.Form[ID + "_input"] != null &&
                                 !string.IsNullOrEmpty(Page.Request.Form[ID + "_input"]))
                        {
                            CurrentPageIndex = Convert.ToInt32(Page.Request.Form[ID + "_input"]);
                        }

                        if (Page.Request.Form[ID + "_size"] != null &&
                            !string.IsNullOrEmpty(Page.Request.Form[ID + "_size"]))
                        {
                            int size = Convert.ToInt32(Page.Request.Form[ID + "_size"]);
                            if (size > 0)
                            {
                                pageSize = size;
                            }
                        }
                        //此处修改了分页控件的分页事件
                        if (PageChanged != null)
                            PageChanged(this, EventArgs.Empty);
                    }
                }
            }
            //处理url参数
            else if (Page.Request.QueryString["page"] != null)
            {
                CurrentPageIndex = Convert.ToInt32(Page.Request.QueryString["page"]);
            }

            Page.Session[KEY_URL] = Page.Request.Url.AbsoluteUri;

        }
        /// <summary>
        /// 计算总页数
        /// </summary>
        private void CountPage()
        {
            pageCount = RecordCount / pageSize;
            if (RecordCount % pageSize > 0)
                pageCount++;
            if (pageCount == 0)
                pageCount = 1;
        }

        /// <summary>
        /// 获取总页码显示字符串
        /// </summary>
        /// <returns>总页码显示字符串</returns>
        private string GetTotlePageText()
        {
            string str = TotalPageText;
            str = Regex.Replace(str, @"[c|C]+", currentPageIndex.ToString());
            str = Regex.Replace(str, @"[t|T]+", pageCount.ToString());
            str = Regex.Replace(str, @"[i|I]+", pageSize.ToString());
            str = Regex.Replace(str, @"[s|S]+", recordCount.ToString());
            return str;
        }

        /// <summary>
        /// 获取页面链接URL
        /// </summary>
        /// <returns>页面链接URL</returns>
        private string GetHrefString(bool disabled, int index, string text, string css = "")
        {
            string tagName = disabled ? "span" : "a";
            string str = string.Format("<{0} ", tagName);
            if (!disabled)
                str += string.Format("href=\"javascript:__doPostBack('{0}','{1}')\" ", ID, index);
            if (!string.IsNullOrEmpty(css))
                str += string.Format("class='{0}' ", css);
            str += string.Format(">{0}</{1}>", text, tagName);
            return str;
        }

        protected override void Render(HtmlTextWriter output)
        {
            if (DesignMode)
            {
                output.Write("OFPager:" + ID);
            }
            else
            {
                if (alwaysShow || pageCount > 1)
                {
                    output.Write("<div id={0} class='{1}'>", ID, CssClass);
                }
                if (showSizeSelect)
                {
                    output.Write("每页显示<select name=\"" + ID + "_size\" id=\"" + ID + "_size\" onchange=\"__doPostBack('" + ID + "','')\">");
                    output.Write("<option value=\"10\" " + (pageSize == 10 ? "selected=\"true\"" : "") + ">" + 10 + "</option>");
                    output.Write("<option value=\"20\" " + (pageSize == 20 ? "selected=\"true\"" : "") + ">" + 20 + "</option>");
                    output.Write("<option value=\"50\" " + (pageSize == 50 ? "selected=\"true\"" : "") + ">" + 50 + "</option>");
                    output.Write("<option value=\"100\" " + (pageSize == 100 ? "selected=\"true\"" : "") + ">" + 100 + "</option>");
                    output.Write("</select>条");
                }
                if (alwaysShow || pageCount > 1)
                {
                    if (showTotalPageText)
                    {
                        output.Write("<span class=\"{0}\">{1}</span>", TotalPageTextClass, GetTotlePageText());
                    }
                    if (showFirstLast)
                    {
                        output.Write(GetHrefString(currentPageIndex == 1, 1, firstPageText, firstButtonsClass));
                    }
                    if (showPrevNext)
                    {
                        output.Write(GetHrefString(currentPageIndex == 1, currentPageIndex - 1, prevPageText, PrevButtonsClass));
                    }
                    var i = currentPageIndex - sidePageCount;

                    if (i == 2)
                    {
                        i = 1;
                    }
                    if (alwaysShowFirstLastPageNumber && i > 1)
                    {
                        output.Write(GetHrefString(currentPageIndex == 1, 1, "1"));
                    }
                    if (i > 2)
                    {
                        output.Write(i == 3 ? GetHrefString(false, i - 1, "2") : GetHrefString(false, i - 1, "..."));
                    }
                    for (; i < currentPageIndex; i++)
                    {
                        if (i > 0)
                        {
                            output.Write(GetHrefString(false, i, i.ToString()));
                        }
                    }

                    output.Write(GetHrefString(true, currentPageIndex, currentPageIndex.ToString(), currentPageButtonClass));

                    var max = currentPageIndex + sidePageCount;
                    if (max == pageCount - 1)
                        max = pageCount;
                    for (i = currentPageIndex + 1; i <= max; i++)
                    {
                        if (i <= pageCount)
                        {
                            output.Write(GetHrefString(false, i, i.ToString()));
                        }
                    }
                    if (i < pageCount)
                    {
                        output.Write(i == PageCount - 1
                                         ? GetHrefString(false, i, i.ToString())
                                         : GetHrefString(false, i, "..."));
                    }

                    if (alwaysShowFirstLastPageNumber && i < pageCount)
                    {
                        output.Write(GetHrefString(currentPageIndex == pageCount, pageCount, pageCount.ToString()));
                    }

                    if (showPrevNext)
                    {
                        output.Write(GetHrefString(currentPageIndex == pageCount, currentPageIndex + 1, nextPageText, NextButtonsClass));
                    }

                    if (showFirstLast)
                    {
                        output.Write(GetHrefString(currentPageIndex == pageCount, pageCount, lastPageText, LastButtonsClass));
                    }
                    if (pageCount > 1 && showSelect)
                    {
                        output.Write("<select name=\"{0}_input\" id=\"{0}_input\" onchange=\"__doPostBack('{0}','')\">", ID);
                        for (i = 1; i <= pageCount; i++)
                        {
                            output.Write("<option value=\"{0}\" {1}>{0}</option>", i, (i == currentPageIndex ? "selected=\"true\"" : ""));
                        }
                        output.Write("</select>");
                    }
                    output.Write("</div>");
                }
            }
        }
    }
}